using System.Collections.Generic;

namespace Avalonia.Media.TextFormatting.Unicode
{
    internal static class PropertyValueAliasHelper
    {
        private static readonly Dictionary<Script, string> s_scriptToTag = 
            new Dictionary<Script, string>{
                { Script.Unknown, "Zzzz"},
                { Script.Common, "Zyyy"},
                { Script.Inherited, "Zinh"},
                { Script.Adlam, "Adlm"},
                { Script.CaucasianAlbanian, "Aghb"},
                { Script.Ahom, "Ahom"},
                { Script.Arabic, "Arab"},
                { Script.ImperialAramaic, "Armi"},
                { Script.Armenian, "Armn"},
                { Script.Avestan, "Avst"},
                { Script.Balinese, "Bali"},
                { Script.Bamum, "Bamu"},
                { Script.BassaVah, "Bass"},
                { Script.Batak, "Batk"},
                { Script.Bengali, "Beng"},
                { Script.Bhaiksuki, "Bhks"},
                { Script.Bopomofo, "Bopo"},
                { Script.Brahmi, "Brah"},
                { Script.Braille, "Brai"},
                { Script.Buginese, "Bugi"},
                { Script.Buhid, "Buhd"},
                { Script.Chakma, "Cakm"},
                { Script.CanadianAboriginal, "Cans"},
                { Script.Carian, "Cari"},
                { Script.Cham, "Cham"},
                { Script.Cherokee, "Cher"},
                { Script.Chorasmian, "Chrs"},
                { Script.Coptic, "Copt"},
                { Script.CyproMinoan, "Cpmn"},
                { Script.Cypriot, "Cprt"},
                { Script.Cyrillic, "Cyrl"},
                { Script.Devanagari, "Deva"},
                { Script.DivesAkuru, "Diak"},
                { Script.Dogra, "Dogr"},
                { Script.Deseret, "Dsrt"},
                { Script.Duployan, "Dupl"},
                { Script.EgyptianHieroglyphs, "Egyp"},
                { Script.Elbasan, "Elba"},
                { Script.Elymaic, "Elym"},
                { Script.Ethiopic, "Ethi"},
                { Script.Georgian, "Geor"},
                { Script.Glagolitic, "Glag"},
                { Script.GunjalaGondi, "Gong"},
                { Script.MasaramGondi, "Gonm"},
                { Script.Gothic, "Goth"},
                { Script.Grantha, "Gran"},
                { Script.Greek, "Grek"},
                { Script.Gujarati, "Gujr"},
                { Script.Gurmukhi, "Guru"},
                { Script.Hangul, "Hang"},
                { Script.Han, "Hani"},
                { Script.Hanunoo, "Hano"},
                { Script.Hatran, "Hatr"},
                { Script.Hebrew, "Hebr"},
                { Script.Hiragana, "Hira"},
                { Script.AnatolianHieroglyphs, "Hluw"},
                { Script.PahawhHmong, "Hmng"},
                { Script.NyiakengPuachueHmong, "Hmnp"},
                { Script.KatakanaOrHiragana, "Hrkt"},
                { Script.OldHungarian, "Hung"},
                { Script.OldItalic, "Ital"},
                { Script.Javanese, "Java"},
                { Script.KayahLi, "Kali"},
                { Script.Katakana, "Kana"},
                { Script.Kawi, "Kawi"},
                { Script.Kharoshthi, "Khar"},
                { Script.Khmer, "Khmr"},
                { Script.Khojki, "Khoj"},
                { Script.KhitanSmallScript, "Kits"},
                { Script.Kannada, "Knda"},
                { Script.Kaithi, "Kthi"},
                { Script.TaiTham, "Lana"},
                { Script.Lao, "Laoo"},
                { Script.Latin, "Latn"},
                { Script.Lepcha, "Lepc"},
                { Script.Limbu, "Limb"},
                { Script.LinearA, "Lina"},
                { Script.LinearB, "Linb"},
                { Script.Lisu, "Lisu"},
                { Script.Lycian, "Lyci"},
                { Script.Lydian, "Lydi"},
                { Script.Mahajani, "Mahj"},
                { Script.Makasar, "Maka"},
                { Script.Mandaic, "Mand"},
                { Script.Manichaean, "Mani"},
                { Script.Marchen, "Marc"},
                { Script.Medefaidrin, "Medf"},
                { Script.MendeKikakui, "Mend"},
                { Script.MeroiticCursive, "Merc"},
                { Script.MeroiticHieroglyphs, "Mero"},
                { Script.Malayalam, "Mlym"},
                { Script.Modi, "Modi"},
                { Script.Mongolian, "Mong"},
                { Script.Mro, "Mroo"},
                { Script.MeeteiMayek, "Mtei"},
                { Script.Multani, "Mult"},
                { Script.Myanmar, "Mymr"},
                { Script.NagMundari, "Nagm"},
                { Script.Nandinagari, "Nand"},
                { Script.OldNorthArabian, "Narb"},
                { Script.Nabataean, "Nbat"},
                { Script.Newa, "Newa"},
                { Script.Nko, "Nkoo"},
                { Script.Nushu, "Nshu"},
                { Script.Ogham, "Ogam"},
                { Script.OlChiki, "Olck"},
                { Script.OldTurkic, "Orkh"},
                { Script.Oriya, "Orya"},
                { Script.Osage, "Osge"},
                { Script.Osmanya, "Osma"},
                { Script.OldUyghur, "Ougr"},
                { Script.Palmyrene, "Palm"},
                { Script.PauCinHau, "Pauc"},
                { Script.OldPermic, "Perm"},
                { Script.PhagsPa, "Phag"},
                { Script.InscriptionalPahlavi, "Phli"},
                { Script.PsalterPahlavi, "Phlp"},
                { Script.Phoenician, "Phnx"},
                { Script.Miao, "Plrd"},
                { Script.InscriptionalParthian, "Prti"},
                { Script.Rejang, "Rjng"},
                { Script.HanifiRohingya, "Rohg"},
                { Script.Runic, "Runr"},
                { Script.Samaritan, "Samr"},
                { Script.OldSouthArabian, "Sarb"},
                { Script.Saurashtra, "Saur"},
                { Script.SignWriting, "Sgnw"},
                { Script.Shavian, "Shaw"},
                { Script.Sharada, "Shrd"},
                { Script.Siddham, "Sidd"},
                { Script.Khudawadi, "Sind"},
                { Script.Sinhala, "Sinh"},
                { Script.Sogdian, "Sogd"},
                { Script.OldSogdian, "Sogo"},
                { Script.SoraSompeng, "Sora"},
                { Script.Soyombo, "Soyo"},
                { Script.Sundanese, "Sund"},
                { Script.SylotiNagri, "Sylo"},
                { Script.Syriac, "Syrc"},
                { Script.Tagbanwa, "Tagb"},
                { Script.Takri, "Takr"},
                { Script.TaiLe, "Tale"},
                { Script.NewTaiLue, "Talu"},
                { Script.Tamil, "Taml"},
                { Script.Tangut, "Tang"},
                { Script.TaiViet, "Tavt"},
                { Script.Telugu, "Telu"},
                { Script.Tifinagh, "Tfng"},
                { Script.Tagalog, "Tglg"},
                { Script.Thaana, "Thaa"},
                { Script.Thai, "Thai"},
                { Script.Tibetan, "Tibt"},
                { Script.Tirhuta, "Tirh"},
                { Script.Tangsa, "Tnsa"},
                { Script.Toto, "Toto"},
                { Script.Ugaritic, "Ugar"},
                { Script.Vai, "Vaii"},
                { Script.Vithkuqi, "Vith"},
                { Script.WarangCiti, "Wara"},
                { Script.Wancho, "Wcho"},
                { Script.OldPersian, "Xpeo"},
                { Script.Cuneiform, "Xsux"},
                { Script.Yezidi, "Yezi"},
                { Script.Yi, "Yiii"},
                { Script.ZanabazarSquare, "Zanb"},
        };

        public static string GetTag(Script script)
        {
            if (!s_scriptToTag.TryGetValue(script, out var value))
            {
                return "Zzzz";
            }
            return value;
        }

        private static readonly Dictionary<string, Script> s_tagToScript = 
            new Dictionary<string,Script>{
                { "Zzzz", Script.Unknown},
                { "Zyyy", Script.Common},
                { "Zinh", Script.Inherited},
                { "Adlm", Script.Adlam},
                { "Aghb", Script.CaucasianAlbanian},
                { "Ahom", Script.Ahom},
                { "Arab", Script.Arabic},
                { "Armi", Script.ImperialAramaic},
                { "Armn", Script.Armenian},
                { "Avst", Script.Avestan},
                { "Bali", Script.Balinese},
                { "Bamu", Script.Bamum},
                { "Bass", Script.BassaVah},
                { "Batk", Script.Batak},
                { "Beng", Script.Bengali},
                { "Bhks", Script.Bhaiksuki},
                { "Bopo", Script.Bopomofo},
                { "Brah", Script.Brahmi},
                { "Brai", Script.Braille},
                { "Bugi", Script.Buginese},
                { "Buhd", Script.Buhid},
                { "Cakm", Script.Chakma},
                { "Cans", Script.CanadianAboriginal},
                { "Cari", Script.Carian},
                { "Cham", Script.Cham},
                { "Cher", Script.Cherokee},
                { "Chrs", Script.Chorasmian},
                { "Copt", Script.Coptic},
                { "Cpmn", Script.CyproMinoan},
                { "Cprt", Script.Cypriot},
                { "Cyrl", Script.Cyrillic},
                { "Deva", Script.Devanagari},
                { "Diak", Script.DivesAkuru},
                { "Dogr", Script.Dogra},
                { "Dsrt", Script.Deseret},
                { "Dupl", Script.Duployan},
                { "Egyp", Script.EgyptianHieroglyphs},
                { "Elba", Script.Elbasan},
                { "Elym", Script.Elymaic},
                { "Ethi", Script.Ethiopic},
                { "Geor", Script.Georgian},
                { "Glag", Script.Glagolitic},
                { "Gong", Script.GunjalaGondi},
                { "Gonm", Script.MasaramGondi},
                { "Goth", Script.Gothic},
                { "Gran", Script.Grantha},
                { "Grek", Script.Greek},
                { "Gujr", Script.Gujarati},
                { "Guru", Script.Gurmukhi},
                { "Hang", Script.Hangul},
                { "Hani", Script.Han},
                { "Hano", Script.Hanunoo},
                { "Hatr", Script.Hatran},
                { "Hebr", Script.Hebrew},
                { "Hira", Script.Hiragana},
                { "Hluw", Script.AnatolianHieroglyphs},
                { "Hmng", Script.PahawhHmong},
                { "Hmnp", Script.NyiakengPuachueHmong},
                { "Hrkt", Script.KatakanaOrHiragana},
                { "Hung", Script.OldHungarian},
                { "Ital", Script.OldItalic},
                { "Java", Script.Javanese},
                { "Kali", Script.KayahLi},
                { "Kana", Script.Katakana},
                { "Kawi", Script.Kawi},
                { "Khar", Script.Kharoshthi},
                { "Khmr", Script.Khmer},
                { "Khoj", Script.Khojki},
                { "Kits", Script.KhitanSmallScript},
                { "Knda", Script.Kannada},
                { "Kthi", Script.Kaithi},
                { "Lana", Script.TaiTham},
                { "Laoo", Script.Lao},
                { "Latn", Script.Latin},
                { "Lepc", Script.Lepcha},
                { "Limb", Script.Limbu},
                { "Lina", Script.LinearA},
                { "Linb", Script.LinearB},
                { "Lisu", Script.Lisu},
                { "Lyci", Script.Lycian},
                { "Lydi", Script.Lydian},
                { "Mahj", Script.Mahajani},
                { "Maka", Script.Makasar},
                { "Mand", Script.Mandaic},
                { "Mani", Script.Manichaean},
                { "Marc", Script.Marchen},
                { "Medf", Script.Medefaidrin},
                { "Mend", Script.MendeKikakui},
                { "Merc", Script.MeroiticCursive},
                { "Mero", Script.MeroiticHieroglyphs},
                { "Mlym", Script.Malayalam},
                { "Modi", Script.Modi},
                { "Mong", Script.Mongolian},
                { "Mroo", Script.Mro},
                { "Mtei", Script.MeeteiMayek},
                { "Mult", Script.Multani},
                { "Mymr", Script.Myanmar},
                { "Nagm", Script.NagMundari},
                { "Nand", Script.Nandinagari},
                { "Narb", Script.OldNorthArabian},
                { "Nbat", Script.Nabataean},
                { "Newa", Script.Newa},
                { "Nkoo", Script.Nko},
                { "Nshu", Script.Nushu},
                { "Ogam", Script.Ogham},
                { "Olck", Script.OlChiki},
                { "Orkh", Script.OldTurkic},
                { "Orya", Script.Oriya},
                { "Osge", Script.Osage},
                { "Osma", Script.Osmanya},
                { "Ougr", Script.OldUyghur},
                { "Palm", Script.Palmyrene},
                { "Pauc", Script.PauCinHau},
                { "Perm", Script.OldPermic},
                { "Phag", Script.PhagsPa},
                { "Phli", Script.InscriptionalPahlavi},
                { "Phlp", Script.PsalterPahlavi},
                { "Phnx", Script.Phoenician},
                { "Plrd", Script.Miao},
                { "Prti", Script.InscriptionalParthian},
                { "Rjng", Script.Rejang},
                { "Rohg", Script.HanifiRohingya},
                { "Runr", Script.Runic},
                { "Samr", Script.Samaritan},
                { "Sarb", Script.OldSouthArabian},
                { "Saur", Script.Saurashtra},
                { "Sgnw", Script.SignWriting},
                { "Shaw", Script.Shavian},
                { "Shrd", Script.Sharada},
                { "Sidd", Script.Siddham},
                { "Sind", Script.Khudawadi},
                { "Sinh", Script.Sinhala},
                { "Sogd", Script.Sogdian},
                { "Sogo", Script.OldSogdian},
                { "Sora", Script.SoraSompeng},
                { "Soyo", Script.Soyombo},
                { "Sund", Script.Sundanese},
                { "Sylo", Script.SylotiNagri},
                { "Syrc", Script.Syriac},
                { "Tagb", Script.Tagbanwa},
                { "Takr", Script.Takri},
                { "Tale", Script.TaiLe},
                { "Talu", Script.NewTaiLue},
                { "Taml", Script.Tamil},
                { "Tang", Script.Tangut},
                { "Tavt", Script.TaiViet},
                { "Telu", Script.Telugu},
                { "Tfng", Script.Tifinagh},
                { "Tglg", Script.Tagalog},
                { "Thaa", Script.Thaana},
                { "Thai", Script.Thai},
                { "Tibt", Script.Tibetan},
                { "Tirh", Script.Tirhuta},
                { "Tnsa", Script.Tangsa},
                { "Toto", Script.Toto},
                { "Ugar", Script.Ugaritic},
                { "Vaii", Script.Vai},
                { "Vith", Script.Vithkuqi},
                { "Wara", Script.WarangCiti},
                { "Wcho", Script.Wancho},
                { "Xpeo", Script.OldPersian},
                { "Xsux", Script.Cuneiform},
                { "Yezi", Script.Yezidi},
                { "Yiii", Script.Yi},
                { "Zanb", Script.ZanabazarSquare},
        };

        public static Script GetScript(string tag)
        {
            if (!s_tagToScript.TryGetValue(tag, out var value))
            {
                return Script.Unknown;
            }
            return value;
        }

        private static readonly Dictionary<string, GeneralCategory> s_tagToGeneralCategory = 
            new Dictionary<string,GeneralCategory>{
                { "C", GeneralCategory.Other},
                { "Cc", GeneralCategory.Control},
                { "Cf", GeneralCategory.Format},
                { "Cn", GeneralCategory.Unassigned},
                { "Co", GeneralCategory.PrivateUse},
                { "Cs", GeneralCategory.Surrogate},
                { "L", GeneralCategory.Letter},
                { "LC", GeneralCategory.CasedLetter},
                { "Ll", GeneralCategory.LowercaseLetter},
                { "Lm", GeneralCategory.ModifierLetter},
                { "Lo", GeneralCategory.OtherLetter},
                { "Lt", GeneralCategory.TitlecaseLetter},
                { "Lu", GeneralCategory.UppercaseLetter},
                { "M", GeneralCategory.Mark},
                { "Mc", GeneralCategory.SpacingMark},
                { "Me", GeneralCategory.EnclosingMark},
                { "Mn", GeneralCategory.NonspacingMark},
                { "N", GeneralCategory.Number},
                { "Nd", GeneralCategory.DecimalNumber},
                { "Nl", GeneralCategory.LetterNumber},
                { "No", GeneralCategory.OtherNumber},
                { "P", GeneralCategory.Punctuation},
                { "Pc", GeneralCategory.ConnectorPunctuation},
                { "Pd", GeneralCategory.DashPunctuation},
                { "Pe", GeneralCategory.ClosePunctuation},
                { "Pf", GeneralCategory.FinalPunctuation},
                { "Pi", GeneralCategory.InitialPunctuation},
                { "Po", GeneralCategory.OtherPunctuation},
                { "Ps", GeneralCategory.OpenPunctuation},
                { "S", GeneralCategory.Symbol},
                { "Sc", GeneralCategory.CurrencySymbol},
                { "Sk", GeneralCategory.ModifierSymbol},
                { "Sm", GeneralCategory.MathSymbol},
                { "So", GeneralCategory.OtherSymbol},
                { "Z", GeneralCategory.Separator},
                { "Zl", GeneralCategory.LineSeparator},
                { "Zp", GeneralCategory.ParagraphSeparator},
                { "Zs", GeneralCategory.SpaceSeparator},
        };

        public static GeneralCategory GetGeneralCategory(string tag)
        {
            if (!s_tagToGeneralCategory.TryGetValue(tag, out var value))
            {
                return GeneralCategory.Other;
            }
            return value;
        }

        private static readonly Dictionary<string, LineBreakClass> s_tagToLineBreakClass = 
            new Dictionary<string,LineBreakClass>{
                { "OP", LineBreakClass.OpenPunctuation},
                { "CL", LineBreakClass.ClosePunctuation},
                { "CP", LineBreakClass.CloseParenthesis},
                { "QU", LineBreakClass.Quotation},
                { "GL", LineBreakClass.Glue},
                { "NS", LineBreakClass.Nonstarter},
                { "EX", LineBreakClass.Exclamation},
                { "SY", LineBreakClass.BreakSymbols},
                { "IS", LineBreakClass.InfixNumeric},
                { "PR", LineBreakClass.PrefixNumeric},
                { "PO", LineBreakClass.PostfixNumeric},
                { "NU", LineBreakClass.Numeric},
                { "AL", LineBreakClass.Alphabetic},
                { "HL", LineBreakClass.HebrewLetter},
                { "ID", LineBreakClass.Ideographic},
                { "IN", LineBreakClass.Inseparable},
                { "HY", LineBreakClass.Hyphen},
                { "BA", LineBreakClass.BreakAfter},
                { "BB", LineBreakClass.BreakBefore},
                { "B2", LineBreakClass.BreakBoth},
                { "ZW", LineBreakClass.ZWSpace},
                { "CM", LineBreakClass.CombiningMark},
                { "WJ", LineBreakClass.WordJoiner},
                { "H2", LineBreakClass.H2},
                { "H3", LineBreakClass.H3},
                { "JL", LineBreakClass.JL},
                { "JV", LineBreakClass.JV},
                { "JT", LineBreakClass.JT},
                { "RI", LineBreakClass.RegionalIndicator},
                { "EB", LineBreakClass.EBase},
                { "EM", LineBreakClass.EModifier},
                { "ZWJ", LineBreakClass.ZWJ},
                { "CB", LineBreakClass.ContingentBreak},
                { "XX", LineBreakClass.Unknown},
                { "AI", LineBreakClass.Ambiguous},
                { "BK", LineBreakClass.MandatoryBreak},
                { "CJ", LineBreakClass.ConditionalJapaneseStarter},
                { "CR", LineBreakClass.CarriageReturn},
                { "LF", LineBreakClass.LineFeed},
                { "NL", LineBreakClass.NextLine},
                { "SA", LineBreakClass.ComplexContext},
                { "SG", LineBreakClass.Surrogate},
                { "SP", LineBreakClass.Space},
        };

        public static LineBreakClass GetLineBreakClass(string tag)
        {
            if (!s_tagToLineBreakClass.TryGetValue(tag, out var value))
            {
                return LineBreakClass.Unknown;
            }
            return value;
        }

        private static readonly Dictionary<string, BidiPairedBracketType> s_tagToBidiPairedBracketType = 
            new Dictionary<string,BidiPairedBracketType>{
                { "n", BidiPairedBracketType.None},
                { "c", BidiPairedBracketType.Close},
                { "o", BidiPairedBracketType.Open},
        };

        public static BidiPairedBracketType GetBidiPairedBracketType(string tag)
        {
            if (!s_tagToBidiPairedBracketType.TryGetValue(tag, out var value))
            {
                return BidiPairedBracketType.None;
            }
            return value;
        }

        private static readonly Dictionary<string, BidiClass> s_tagToBidiClass = 
            new Dictionary<string,BidiClass>{
                { "L", BidiClass.LeftToRight},
                { "AL", BidiClass.ArabicLetter},
                { "AN", BidiClass.ArabicNumber},
                { "B", BidiClass.ParagraphSeparator},
                { "BN", BidiClass.BoundaryNeutral},
                { "CS", BidiClass.CommonSeparator},
                { "EN", BidiClass.EuropeanNumber},
                { "ES", BidiClass.EuropeanSeparator},
                { "ET", BidiClass.EuropeanTerminator},
                { "FSI", BidiClass.FirstStrongIsolate},
                { "LRE", BidiClass.LeftToRightEmbedding},
                { "LRI", BidiClass.LeftToRightIsolate},
                { "LRO", BidiClass.LeftToRightOverride},
                { "NSM", BidiClass.NonspacingMark},
                { "ON", BidiClass.OtherNeutral},
                { "PDF", BidiClass.PopDirectionalFormat},
                { "PDI", BidiClass.PopDirectionalIsolate},
                { "R", BidiClass.RightToLeft},
                { "RLE", BidiClass.RightToLeftEmbedding},
                { "RLI", BidiClass.RightToLeftIsolate},
                { "RLO", BidiClass.RightToLeftOverride},
                { "S", BidiClass.SegmentSeparator},
                { "WS", BidiClass.WhiteSpace},
        };

        public static BidiClass GetBidiClass(string tag)
        {
            if (!s_tagToBidiClass.TryGetValue(tag, out var value))
            {
                return BidiClass.LeftToRight;
            }
            return value;
        }

    }
}
